R Sienna example:
rm(list = ls())
fpackage.check <- function(packages) {
lapply(packages, FUN = function(x) {
if (!require(x, character.only = TRUE)) {
install.packages(x, dependencies = TRUE)
library(x, character.only = TRUE)
}
})
}
fsave <- function(x, file = NULL, location = "./data/processed/") {
ifelse(!dir.exists("data"), dir.create("data"), FALSE)
ifelse(!dir.exists("data/processed"), dir.create("data/processed"), FALSE)
if (is.null(file))
file = deparse(substitute(x))
datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
totalname <- paste(location, datename, file, ".rda", sep = "")
save(x, file = totalname) #need to fix if file is reloaded as input name, not as x.
}
fload <- function(filename) {
load(filename)
get(ls()[ls() != "filename"])
}
fshowdf <- function(x, ...) {
knitr::kable(x, digits = 2, "html", ...) %>%
kableExtra::kable_styling(bootstrap_options = c("striped", "hover")) %>%
kableExtra::scroll_box(width = "100%", height = "300px")
}
colorize <- function(x, color) {
sprintf("<span style='color: %s;'>%s</span>", color, x)
}
fpackage.check(packages)
[[1]]
NULL
NEED DATA - use build in datasets from RSIENNA ?s501 Is adjacency
matrix for network type 1. Goal: Follow steps in 7.1 for different
data:
Step 1. Define data
Dependent variable: ties
s502 #network at timepoint 2
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34
1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
3 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
11 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0
12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
14 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
17 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0
18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48 V49 V50
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0
13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
16 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
18 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
19 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0
20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[ reached 'max' / getOption("max.print") -- omitted 30 rows ]
Inspect networks. Remove NAs, make sure diagonal. Need to see binary
(not weighted)
Put networks in an array
c(dim(s501),2)
[1] 50 50 2
could replace this with data set from last week
Define dependent - and independent - variable
# don't need wave 2 - just modeling at independent variable, influencing all ministeps between time 1 and time 2
alcohol
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
3 2 2 2 3 4 4 4 2 4 5 5 3 3 4 4 2 4 3 2 1 3 4 3 3 4 2 2 3 1 4 4 3 2 3 4 2 3 2 1 4 4 2 5
45 46 47 48 49 50
2 2 2 2 1 1
Now combine into dataset - if use Rsiena, need this.
myeff
effectName include fix test initialValue parm
1 basic rate parameter net TRUE FALSE FALSE 4.69604 0
2 outdegree (density) TRUE FALSE FALSE -1.48852 0
3 reciprocity TRUE FALSE FALSE 0.00000 0
Now can look at myeff - look at starting values - has density of two
networks, reciprocity
Want much more statistics for model, though!!
Step 2:
Can see all effects that could include in the dataset. Which is a
lot. And this is a simple dataset. and yeah, its huge. Also can see that
the type depends on weight function (evaluation (), endowment (), and
creation ())
Example. Jochem wants to make tie with Jos. Jochem’s consideration to
make a tie with Jos could be different than consideration to maintain a
tie, could be different that decistions to break a tie. Can’t estimate
all three. Evalution: mechanisms the same for making as breaking,
endowment = maintaining, creation = if there are none then what is the
cost.
In this course: just use evaluation function. Assume mechanisms and
functions to make/break ties are similar. include degree for evaluation.
But what are all these effects? - should be able to calculate statistic
for each effect for an ego in a network… Mathematical formula in chapter
12.
effectsDocumentation(myeff)
Effects documentation written to file myeff.html .
Make sure to understand out degree and reciprocity effects -
statistics - will play around with this next week. Need to think of
theory for which statistics are relevant. - Look at literature for
statistics, think about it, play and see if effects exists - how work in
reality? propose idea, write notation, see if effect exists in manual,
etc. Lots of notation because everyone is looking for their own effects.
- need to include more effects if what to.
Step 3: Look at intial data
- good for deciding statistics to use.
print01Report(mydata)
# gives initial description of data
# reading network variables , covariates, density measures/changes in networks, tie changes between subsequent observations... calculate how much networks changed over time.
# dont use balance calculation
Step 4: Add effects
myeff <- includeEffects(myeff, isolateNet, inPop, outAct)
effectNumber effectName shortName include fix test initialValue parm
1 78 indegree - popularity inPop TRUE FALSE FALSE 0 0
2 106 outdegree - activity outAct TRUE FALSE FALSE 0 0
3 149 network-isolate isolateNet TRUE FALSE FALSE 0 0
outAct - look at the number of times I have and square that:
especially the people that have a lot of ties will send a lot of ties. -
evaluation function of tie1 0 ties, and tie1 4 ties - then at t2 people
who have ties are more likely to send more ties
We know tie distributions are skewed, some people send a lot of ties
and others dont.
inPop: in degree activity: people who reseive a lot of in-degrees
send a lot of out-degrees
isolateNet: people without a lot of indegree nets.
Can see that starting values are 0 – hypothesis testing
Step 5: Estimation
ansM1
Estimates, standard errors and convergence t-ratios
Estimate Standard Convergence
Error t-ratio
Rate parameters:
0 Rate parameter 5.6461 ( 0.8889 )
Other parameters:
1. eval outdegree (density) -2.1186 ( 0.4326 ) -0.0337
2. eval reciprocity 2.4448 ( 0.2376 ) -0.0049
3. eval indegree - popularity 0.0724 ( 0.0638 ) -0.0378
4. eval outdegree - activity -0.0645 ( 0.0676 ) -0.0412
5. eval network-isolate 1.7737 ( 2.2226 ) -0.0120
Overall maximum convergence ratio: 0.0684
Total of 2203 iteration steps.
Now have first estimated Rsiena model!
- see:negative out degree
- 2.4 reciprocity: is important then in this model
- indegree populaty is popular but not significant…
if significant: more indegrees- more likely to send later. people
with more out-degrees - more likely to send less (negative). isolate
more likely to be alone.
Need to think of model that makes sense in this
REVIEWING RSIENA NOW - negative degree - density is less than .5 -
interpretations - Mailing list for TOM
- Now: re-read chapter 2 and chapter 5
Afternoon: play with estimating our own models Nice to do with our
own data - collaboration networks. Logic of RSIENA: took actor oriented
approach - works if ties are directed. if undirected network, logic is
different: the actor deciding on undirected tie is difficult. Advise:
for now treat as undirected - and then evaluate tie. undirected tie by
reach consensus, forced into concensus, etc - reciprocity matters less
now.
Now play with it
Now - referencing web scraping site
fcolnet <- function(data = scholars, university = "RU", discipline = "sociology", waves = list(c(2015,
2018), c(2019, 2023)), type = c("first")) {
# step 1
demographics <- do.call(rbind.data.frame, data$demographics)
demographics <- demographics %>%
mutate(Universiteit1.22 = replace(Universiteit1.22, is.na(Universiteit1.22), ""), Universiteit2.22 = replace(Universiteit2.22,
is.na(Universiteit2.22), ""), Universiteit1.24 = replace(Universiteit1.24, is.na(Universiteit1.24),
""), Universiteit2.24 = replace(Universiteit2.24, is.na(Universiteit2.24), ""), discipline.22 = replace(discipline.22,
is.na(discipline.22), ""), discipline.24 = replace(discipline.24, is.na(discipline.24), ""))
sample <- which((demographics$Universiteit1.22 %in% university | demographics$Universiteit2.22 %in%
university | demographics$Universiteit1.24 %in% university | demographics$Universiteit2.24 %in%
university) & (demographics$discipline.22 %in% discipline | demographics$discipline.24 %in% discipline))
demographics_soc <- demographics[sample, ]
scholars_sel <- lapply(scholars, "[", sample)
# step 2
ids <- demographics_soc$au_id
nwaves <- length(waves)
nets <- array(0, dim = c(nwaves, length(ids), length(ids)), dimnames = list(wave = 1:nwaves, ids,
ids))
dimnames(nets)
# step 3
df_works <- tibble(works_id = unlist(lapply(scholars_sel$work, function(l) l$id)), works_author = unlist(lapply(scholars_sel$work,
function(l) l$author), recursive = FALSE), works_year = unlist(lapply(scholars_sel$work, function(l) l$publication_year),
recursive = FALSE))
df_works <- df_works[!duplicated(df_works), ]
# step 4
if (type == "first") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
ego <- df_works_w$works_author[i][[1]]$au_id[1]
alters <- df_works_w$works_author[i][[1]]$au_id[-1]
if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
}
}
}
}
if (type == "last") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
ego <- rev(df_works_w$works_author[i][[1]]$au_id)[1]
alters <- rev(df_works_w$works_author[i][[1]]$au_id)[-1]
if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
}
}
}
}
if (type == "all") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
egos <- df_works_w$works_author[i][[1]]$au_id
if (sum(ids %in% egos) > 0) {
nets[j, which(ids %in% egos), which(ids %in% egos)] <- 1
}
}
}
}
output <- list()
output$data <- scholars_sel
output$nets <- nets
return(output)
}
Example in class from 10 October Siena dependent variable
answer_ex
Estimates, standard errors and convergence t-ratios
Estimate Standard Convergence
Error t-ratio
Network Dynamics
1. rate constant mynet1 rate (period 1) 5.7880 ( 0.9880 ) 0.0777
2. rate constant mynet1 rate (period 2) 4.5365 ( 0.6468 ) -0.0510
3. eval outdegree (density) -1.9196 ( 0.2519 ) 0.0175
4. eval reciprocity 2.7951 ( 0.1876 ) -0.0070
5. eval unequal mybeh -0.4987 ( 0.3490 ) 0.0032
6. eval unequal smoke -0.1958 ( 0.1405 ) -0.0074
Behavior Dynamics
7. rate rate mybeh (period 1) 1.2022 ( 0.3140 ) 0.0557
8. rate rate mybeh (period 2) 1.6729 ( 0.4611 ) 0.0577
9. eval mybeh linear shape 0.3601 ( 0.1454 ) 0.0118
10. eval mybeh quadratic shape -0.1961 ( 0.0906 ) 0.0197
Overall maximum convergence ratio: 0.1356
Total of 2926 iteration steps.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIFIgU2llbm5hIGV4YW1wbGU6IA0KDQoNCmBgYHtyfQ0Kcm0obGlzdCA9IGxzKCkpDQoNCmZwYWNrYWdlLmNoZWNrIDwtIGZ1bmN0aW9uKHBhY2thZ2VzKSB7DQogICAgbGFwcGx5KHBhY2thZ2VzLCBGVU4gPSBmdW5jdGlvbih4KSB7DQogICAgICAgIGlmICghcmVxdWlyZSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7DQogICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKHgsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICAgICAgICAgICBsaWJyYXJ5KHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiAgICAgICAgfQ0KICAgIH0pDQp9DQoNCmZzYXZlIDwtIGZ1bmN0aW9uKHgsIGZpbGUgPSBOVUxMLCBsb2NhdGlvbiA9ICIuL2RhdGEvcHJvY2Vzc2VkLyIpIHsNCiAgICBpZmVsc2UoIWRpci5leGlzdHMoImRhdGEiKSwgZGlyLmNyZWF0ZSgiZGF0YSIpLCBGQUxTRSkNCiAgICBpZmVsc2UoIWRpci5leGlzdHMoImRhdGEvcHJvY2Vzc2VkIiksIGRpci5jcmVhdGUoImRhdGEvcHJvY2Vzc2VkIiksIEZBTFNFKQ0KICAgIGlmIChpcy5udWxsKGZpbGUpKQ0KICAgICAgICBmaWxlID0gZGVwYXJzZShzdWJzdGl0dXRlKHgpKQ0KICAgIGRhdGVuYW1lIDwtIHN1YnN0cihnc3ViKCJbOi1dIiwgIiIsIFN5cy50aW1lKCkpLCAxLCA4KQ0KICAgIHRvdGFsbmFtZSA8LSBwYXN0ZShsb2NhdGlvbiwgZGF0ZW5hbWUsIGZpbGUsICIucmRhIiwgc2VwID0gIiIpDQogICAgc2F2ZSh4LCBmaWxlID0gdG90YWxuYW1lKSAgI25lZWQgdG8gZml4IGlmIGZpbGUgaXMgcmVsb2FkZWQgYXMgaW5wdXQgbmFtZSwgbm90IGFzIHguIA0KfQ0KDQpmbG9hZCA8LSBmdW5jdGlvbihmaWxlbmFtZSkgew0KICAgIGxvYWQoZmlsZW5hbWUpDQogICAgZ2V0KGxzKClbbHMoKSAhPSAiZmlsZW5hbWUiXSkNCn0NCg0KZnNob3dkZiA8LSBmdW5jdGlvbih4LCAuLi4pIHsNCiAgICBrbml0cjo6a2FibGUoeCwgZGlnaXRzID0gMiwgImh0bWwiLCAuLi4pICU+JQ0KICAgICAgICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpKSAlPiUNCiAgICAgICAga2FibGVFeHRyYTo6c2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikNCn0NCg0KY29sb3JpemUgPC0gZnVuY3Rpb24oeCwgY29sb3IpIHsNCiAgICBzcHJpbnRmKCI8c3BhbiBzdHlsZT0nY29sb3I6ICVzOyc+JXM8L3NwYW4+IiwgY29sb3IsIHgpDQp9DQpgYGANCg0KDQoNCmBgYHtyfQ0KcGFja2FnZXMgPSBjKCJSU2llbmEiLCAiZGV2dG9vbHMiLCAiaWdyYXBoIikNCmZwYWNrYWdlLmNoZWNrKHBhY2thZ2VzKQ0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoJ0pvY2hlbVRvbHNtYS9Sc2llbmFUd29TdGVwJywgYnVpbGRfdmlnbmV0dGVzPVRSVUUpDQpwYWNrYWdlcyA9IGMoIlJzaWVuYVR3b1N0ZXAiKQ0KZnBhY2thZ2UuY2hlY2socGFja2FnZXMpDQpgYGANCg0KTkVFRCBEQVRBIC0gdXNlIGJ1aWxkIGluIGRhdGFzZXRzIGZyb20gUlNJRU5OQSANCj9zNTAxDQpJcyBhZGphY2VuY3kgbWF0cml4IGZvciBuZXR3b3JrIHR5cGUgMS4gR29hbDogRm9sbG93IHN0ZXBzIGluIDcuMSBmb3IgZGlmZmVyZW50IGRhdGE6DQoNCiMgU3RlcCAxLiBEZWZpbmUgZGF0YQ0KRGVwZW5kZW50IHZhcmlhYmxlOiB0aWVzIA0KDQoNCmBgYHtyfQ0KczUwMSAjbmV0d29yayBhdCB0aW1lcG9pbnQgMQ0KczUwMiAjbmV0d29yayBhdCB0aW1lcG9pbnQgMg0KYGBgDQoNCg0KSW5zcGVjdCBuZXR3b3Jrcy4gUmVtb3ZlIE5BcywgbWFrZSBzdXJlIGRpYWdvbmFsLiBOZWVkIHRvIHNlZSBiaW5hcnkgKG5vdCB3ZWlnaHRlZCkNCmBgYHtyfQ0KDQpgYGANCg0KDQpQdXQgbmV0d29ya3MgaW4gYW4gYXJyYXkNCmBgYHtyfQ0KDQpkaW0oczUwMSkgI3NheXMgNTB4NTA6IDUwIHJvd3MsIDUwIGNvbHVtbnMgaW4gZGF0YS4gDQoNCm5ldHMgPC0gYXJyYXkgKGRhdGEgPSBjKHM1MDEsIHM1MDIpLCBkaW0gPSBjKGRpbShzNTAxKSwgMikpICMNCmMoZGltKHM1MDEpLDIpDQoNCiMgZGltZW50aW9ucyBvZiBhcnJheSBhcmUgbnVtYmVyIG9mIGNvbHVtbnMgYW5kIG51bWJlciBvZiByb3dzIA0KYGBgDQogY291bGQgcmVwbGFjZSB0aGlzIHdpdGggZGF0YSBzZXQgZnJvbSBsYXN0IHdlZWsgDQogDQogDQpEZWZpbmUgZGVwZW5kZW50IC0gYW5kIGluZGVwZW5kZW50IC0gdmFyaWFibGUNCmBgYHtyfQ0KDQpuZXQgPC0gc2llbmFEZXBlbmRlbnQobmV0cykgI2RlcGVuZGVudCB2YXJpYWJsZSANCg0KICAjIGluZGVwZW5kZW50IHZhcmlhYmxlIC0gczUwYSAtIHdlIHdpbGwgdGFrZSBmaXJzdCB3YXkgDQphbGNvaG9sIDwtIHM1MGFbLDFdYWxjb2hvbA0KICMgZG9uJ3QgbmVlZCB3YXZlIDIgLSBqdXN0IG1vZGVsaW5nIGF0IGluZGVwZW5kZW50IHZhcmlhYmxlLCBpbmZsdWVuY2luZyBhbGwgbWluaXN0ZXBzIGJldHdlZW4gdGltZSAxIGFuZCB0aW1lIDIgDQphbGNvaG9sIA0KIA0KYWxjb2hvbCA8LSBjb0NvdmFyKGFsY29ob2wpIyBhdCBhY3RvciBsZXZlbCAtIG1lYW4gY2VudGVyZWQgLSBpcyBhIHRpbWUgY29uc3RhbnQgY29WYXJpYXRlIA0KYGBgDQoNCk5vdyBjb21iaW5lIGludG8gZGF0YXNldCAtIGlmIHVzZSBSc2llbmEsIG5lZWQgdGhpcy4gDQpgYGB7cn0NCm15ZGF0YSA8LSBzaWVuYURhdGFDcmVhdGUobmV0LCBhbGNvaG9sKQ0KDQpteWVmZiA8LSBnZXRFZmZlY3RzKG15ZGF0YSkgI2hhdmUgYSBsb29rIA0KbXllZmYNCmBgYA0KTm93IGNhbiBsb29rIGF0IG15ZWZmIC0gbG9vayBhdCBzdGFydGluZyB2YWx1ZXMgLSBoYXMgZGVuc2l0eSBvZiB0d28gbmV0d29ya3MsIHJlY2lwcm9jaXR5IA0KDQoNCldhbnQgbXVjaCBtb3JlIHN0YXRpc3RpY3MgZm9yIG1vZGVsLCB0aG91Z2ghISANCg0KIyBTdGVwIDI6IA0KQ2FuIHNlZSBhbGwgZWZmZWN0cyB0aGF0IGNvdWxkIGluY2x1ZGUgaW4gdGhlIGRhdGFzZXQuIFdoaWNoIGlzIGEgbG90LiBBbmQgdGhpcyBpcyBhIHNpbXBsZSBkYXRhc2V0LiBhbmQgeWVhaCwgaXRzIGh1Z2UuIEFsc28gY2FuIHNlZSB0aGF0IHRoZSB0eXBlIGRlcGVuZHMgb24gd2VpZ2h0IGZ1bmN0aW9uIChldmFsdWF0aW9uICgpLCBlbmRvd21lbnQgKCksIGFuZCBjcmVhdGlvbiAoKSkNCg0KRXhhbXBsZS4gSm9jaGVtIHdhbnRzIHRvIG1ha2UgdGllIHdpdGggSm9zLiBKb2NoZW0ncyBjb25zaWRlcmF0aW9uIHRvIG1ha2UgYSB0aWUgd2l0aCBKb3MgY291bGQgYmUgZGlmZmVyZW50IHRoYW4gY29uc2lkZXJhdGlvbiB0byBtYWludGFpbiBhIHRpZSwgY291bGQgYmUgZGlmZmVyZW50IHRoYXQgZGVjaXN0aW9ucyB0byBicmVhayBhIHRpZS4gQ2FuJ3QgZXN0aW1hdGUgYWxsIHRocmVlLiBFdmFsdXRpb246IG1lY2hhbmlzbXMgdGhlIHNhbWUgZm9yIG1ha2luZyBhcyBicmVha2luZywgZW5kb3dtZW50ID0gbWFpbnRhaW5pbmcsIGNyZWF0aW9uID0gaWYgdGhlcmUgYXJlIG5vbmUgdGhlbiB3aGF0IGlzIHRoZSBjb3N0LiANCg0KSW4gdGhpcyBjb3Vyc2U6IGp1c3QgdXNlIGV2YWx1YXRpb24gZnVuY3Rpb24uIEFzc3VtZSBtZWNoYW5pc21zIGFuZCBmdW5jdGlvbnMgdG8gbWFrZS9icmVhayB0aWVzIGFyZSBzaW1pbGFyLiBpbmNsdWRlIGRlZ3JlZSBmb3IgZXZhbHVhdGlvbi4gQnV0IHdoYXQgYXJlIGFsbCB0aGVzZSBlZmZlY3RzPyANCi0gICAgc2hvdWxkIGJlIGFibGUgdG8gY2FsY3VsYXRlIHN0YXRpc3RpYyBmb3IgZWFjaCBlZmZlY3QgZm9yIGFuIGVnbyBpbiBhIG5ldHdvcmsuLi4gTWF0aGVtYXRpY2FsIGZvcm11bGEgaW4gY2hhcHRlciAxMi4gDQoNCg0KYGBge3J9DQplZmZlY3RzRG9jdW1lbnRhdGlvbihteWVmZikNCmBgYA0KDQoNCk1ha2Ugc3VyZSB0byB1bmRlcnN0YW5kIG91dCBkZWdyZWUgYW5kIHJlY2lwcm9jaXR5IGVmZmVjdHMgLSBzdGF0aXN0aWNzIC0gd2lsbCBwbGF5IGFyb3VuZCB3aXRoIHRoaXMgbmV4dCB3ZWVrLiBOZWVkIHRvIHRoaW5rIG9mIHRoZW9yeSBmb3Igd2hpY2ggc3RhdGlzdGljcyBhcmUgcmVsZXZhbnQuIA0KLSAgICBMb29rIGF0IGxpdGVyYXR1cmUgZm9yIHN0YXRpc3RpY3MsIHRoaW5rIGFib3V0IGl0LCBwbGF5IGFuZCBzZWUgaWYgZWZmZWN0cyBleGlzdHMgDQotICAgIGhvdyB3b3JrIGluIHJlYWxpdHk/IHByb3Bvc2UgaWRlYSwgd3JpdGUgbm90YXRpb24sIHNlZSBpZiBlZmZlY3QgZXhpc3RzIGluIG1hbnVhbCwgZXRjLiBMb3RzIG9mIG5vdGF0aW9uIGJlY2F1c2UgZXZlcnlvbmUgaXMgbG9va2luZyBmb3IgdGhlaXIgb3duIGVmZmVjdHMuIA0KLSAgICBuZWVkIHRvIGluY2x1ZGUgbW9yZSBlZmZlY3RzIGlmIHdoYXQgdG8uIA0KDQpgYGB7cn0NCg0KYGBgDQoNCg0KDQojIFN0ZXAgMzogTG9vayBhdCBpbnRpYWwgZGF0YQ0KLSAgICBnb29kIGZvciBkZWNpZGluZyBzdGF0aXN0aWNzIHRvIHVzZS4gDQpgYGB7cn0NCnByaW50MDFSZXBvcnQobXlkYXRhKQ0KDQojIGdpdmVzIGluaXRpYWwgZGVzY3JpcHRpb24gb2YgZGF0YSANCiMgcmVhZGluZyBuZXR3b3JrIHZhcmlhYmxlcyAsIGNvdmFyaWF0ZXMsIGRlbnNpdHkgbWVhc3VyZXMvY2hhbmdlcyBpbiBuZXR3b3JrcywgdGllIGNoYW5nZXMgYmV0d2VlbiBzdWJzZXF1ZW50IG9ic2VydmF0aW9ucy4uLiBjYWxjdWxhdGUgaG93IG11Y2ggbmV0d29ya3MgY2hhbmdlZCBvdmVyIHRpbWUuIA0KIyBkb250IHVzZSBiYWxhbmNlIGNhbGN1bGF0aW9uIA0KYGBgDQoNCiMgU3RlcCA0OiBBZGQgZWZmZWN0cw0KDQpgYGB7cn0NCm15ZWZmIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmLCBpc29sYXRlTmV0LCBpblBvcCwgb3V0QWN0KQ0KDQojb3V0QWN0IC0gb3V0ZGVncmVlIHJlbGF0ZWQgYWN0aXZpdHkgDQpgYGANCg0Kb3V0QWN0DQotIGxvb2sgYXQgdGhlIG51bWJlciBvZiB0aW1lcyBJIGhhdmUgYW5kIHNxdWFyZSB0aGF0OiBlc3BlY2lhbGx5IHRoZSBwZW9wbGUgdGhhdCBoYXZlIGEgbG90IG9mIHRpZXMgd2lsbCBzZW5kIGEgbG90IG9mIHRpZXMuIA0KLSBldmFsdWF0aW9uIGZ1bmN0aW9uIG9mIHRpZTEgMCB0aWVzLCBhbmQgdGllMSA0IHRpZXMgLSB0aGVuIGF0IHQyIHBlb3BsZSB3aG8gaGF2ZSB0aWVzIGFyZSBtb3JlIGxpa2VseSB0byBzZW5kIG1vcmUgdGllcyANCg0KV2Uga25vdyB0aWUgZGlzdHJpYnV0aW9ucyBhcmUgc2tld2VkLCBzb21lIHBlb3BsZSBzZW5kIGEgbG90IG9mIHRpZXMgYW5kIG90aGVycyBkb250LiANCg0KaW5Qb3A6IGluIGRlZ3JlZSBhY3Rpdml0eTogcGVvcGxlIHdobyByZXNlaXZlIGEgbG90IG9mIGluLWRlZ3JlZXMgc2VuZCBhIGxvdCBvZiBvdXQtZGVncmVlcyANCg0KaXNvbGF0ZU5ldDogcGVvcGxlIHdpdGhvdXQgYSBsb3Qgb2YgaW5kZWdyZWUgbmV0cy4gDQoNCg0KDQpDYW4gc2VlIHRoYXQgc3RhcnRpbmcgdmFsdWVzIGFyZSAwIC0tIGh5cG90aGVzaXMgdGVzdGluZyANCg0KIyBTdGVwIDU6IEVzdGltYXRpb24NCg0KYGBge3J9DQpteUFsZ29yaXRobSA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0IikNCg0KIyBkZWZpbmUgYWxnb3JpdGhtIHRoYXQgc2F5cyBob3cgSSB3YW50IHRvIGVzdGltYXRlIG15IG1vZGVsLiB3aWxsIHVzZSBkZWZhdWx0cy4gDQoNCmFuc00xIDwtIHNpZW5hMDcobXlBbGdvcml0aG0sIGRhdGEgPSBteWRhdGEsIGVmZmVjdHMgPSBteWVmZiwgcmV0dXJuRGVwcyA9IFRSVUUpDQojIHRoZW4gcnVuIGl0IHRvIHNlZSANCg0KYW5zTTENCg0KYGBgDQpOb3cgaGF2ZSBmaXJzdCBlc3RpbWF0ZWQgUnNpZW5hIG1vZGVsISANCg0KDQotIHNlZTpuZWdhdGl2ZSBvdXQgZGVncmVlIA0KLSAyLjQgcmVjaXByb2NpdHk6IGlzIGltcG9ydGFudCB0aGVuIGluIHRoaXMgbW9kZWwgDQotIGluZGVncmVlIHBvcHVsYXR5IGlzIHBvcHVsYXIgYnV0IG5vdCBzaWduaWZpY2FudC4uLiANCg0KaWYgc2lnbmlmaWNhbnQ6IG1vcmUgaW5kZWdyZWVzLSBtb3JlIGxpa2VseSB0byBzZW5kIGxhdGVyLiBwZW9wbGUgd2l0aCBtb3JlIG91dC1kZWdyZWVzIC0gbW9yZSBsaWtlbHkgdG8gc2VuZCBsZXNzIChuZWdhdGl2ZSkuIGlzb2xhdGUgbW9yZSBsaWtlbHkgdG8gYmUgYWxvbmUuIA0KDQoNCk5lZWQgdG8gdGhpbmsgb2YgbW9kZWwgdGhhdCBtYWtlcyBzZW5zZSBpbiB0aGlzDQoNCg0KYGBge3J9DQoNCmBgYA0KDQpSRVZJRVdJTkcgUlNJRU5BIE5PVw0KLSAgIG5lZ2F0aXZlIGRlZ3JlZSAtIGRlbnNpdHkgaXMgbGVzcyB0aGFuIC41IA0KLSAgIGludGVycHJldGF0aW9ucyANCi0gICBNYWlsaW5nIGxpc3QgZm9yIFRPTQ0KDQotICAgTm93OiByZS1yZWFkIGNoYXB0ZXIgMiBhbmQgY2hhcHRlciA1IA0KDQpBZnRlcm5vb246IHBsYXkgd2l0aCBlc3RpbWF0aW5nIG91ciBvd24gbW9kZWxzIA0KTmljZSB0byBkbyB3aXRoIG91ciBvd24gZGF0YSAtIGNvbGxhYm9yYXRpb24gbmV0d29ya3MuIA0KTG9naWMgb2YgUlNJRU5BOiB0b29rIGFjdG9yIG9yaWVudGVkIGFwcHJvYWNoIC0gd29ya3MgaWYgdGllcyBhcmUgZGlyZWN0ZWQuIGlmIHVuZGlyZWN0ZWQgbmV0d29yaywgbG9naWMgaXMgZGlmZmVyZW50OiB0aGUgYWN0b3IgZGVjaWRpbmcgb24gdW5kaXJlY3RlZCB0aWUgaXMgZGlmZmljdWx0LiBBZHZpc2U6IGZvciBub3cgdHJlYXQgYXMgdW5kaXJlY3RlZCAtIGFuZCB0aGVuIGV2YWx1YXRlIHRpZS4gDQp1bmRpcmVjdGVkIHRpZSBieSByZWFjaCBjb25zZW5zdXMsIGZvcmNlZCBpbnRvIGNvbmNlbnN1cywgZXRjIC0gcmVjaXByb2NpdHkgbWF0dGVycyBsZXNzIG5vdy4gDQoNCmBgYHtyfQ0KDQpgYGANCg0KIyBOb3cgcGxheSB3aXRoIGl0IA0KDQpgYGB7cn0NCg0KDQpgYGANCg0KDQpgYGB7cn0NCmBgYA0KDQoNCk5vdyAtIHJlZmVyZW5jaW5nIHdlYiBzY3JhcGluZyBzaXRlIA0KDQpgYGB7cn0NCmZjb2xuZXQgPC0gZnVuY3Rpb24oZGF0YSA9IHNjaG9sYXJzLCB1bml2ZXJzaXR5ID0gIlJVIiwgZGlzY2lwbGluZSA9ICJzb2Npb2xvZ3kiLCB3YXZlcyA9IGxpc3QoYygyMDE1LA0KICAgIDIwMTgpLCBjKDIwMTksIDIwMjMpKSwgdHlwZSA9IGMoImZpcnN0IikpIHsNCg0KICAgICMgc3RlcCAxDQogICAgZGVtb2dyYXBoaWNzIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgZGF0YSRkZW1vZ3JhcGhpY3MpDQogICAgZGVtb2dyYXBoaWNzIDwtIGRlbW9ncmFwaGljcyAlPiUNCiAgICAgICAgbXV0YXRlKFVuaXZlcnNpdGVpdDEuMjIgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDEuMjIsIGlzLm5hKFVuaXZlcnNpdGVpdDEuMjIpLCAiIiksIFVuaXZlcnNpdGVpdDIuMjIgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDIuMjIsDQogICAgICAgICAgICBpcy5uYShVbml2ZXJzaXRlaXQyLjIyKSwgIiIpLCBVbml2ZXJzaXRlaXQxLjI0ID0gcmVwbGFjZShVbml2ZXJzaXRlaXQxLjI0LCBpcy5uYShVbml2ZXJzaXRlaXQxLjI0KSwNCiAgICAgICAgICAgICIiKSwgVW5pdmVyc2l0ZWl0Mi4yNCA9IHJlcGxhY2UoVW5pdmVyc2l0ZWl0Mi4yNCwgaXMubmEoVW5pdmVyc2l0ZWl0Mi4yNCksICIiKSwgZGlzY2lwbGluZS4yMiA9IHJlcGxhY2UoZGlzY2lwbGluZS4yMiwNCiAgICAgICAgICAgIGlzLm5hKGRpc2NpcGxpbmUuMjIpLCAiIiksIGRpc2NpcGxpbmUuMjQgPSByZXBsYWNlKGRpc2NpcGxpbmUuMjQsIGlzLm5hKGRpc2NpcGxpbmUuMjQpLCAiIikpDQoNCiAgICBzYW1wbGUgPC0gd2hpY2goKGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQxLjIyICVpbiUgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQyLjIyICVpbiUNCiAgICAgICAgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQxLjI0ICVpbiUgdW5pdmVyc2l0eSB8IGRlbW9ncmFwaGljcyRVbml2ZXJzaXRlaXQyLjI0ICVpbiUNCiAgICAgICAgdW5pdmVyc2l0eSkgJiAoZGVtb2dyYXBoaWNzJGRpc2NpcGxpbmUuMjIgJWluJSBkaXNjaXBsaW5lIHwgZGVtb2dyYXBoaWNzJGRpc2NpcGxpbmUuMjQgJWluJSBkaXNjaXBsaW5lKSkNCg0KICAgIGRlbW9ncmFwaGljc19zb2MgPC0gZGVtb2dyYXBoaWNzW3NhbXBsZSwgXQ0KICAgIHNjaG9sYXJzX3NlbCA8LSBsYXBwbHkoc2Nob2xhcnMsICJbIiwgc2FtcGxlKQ0KDQogICAgIyBzdGVwIDINCiAgICBpZHMgPC0gZGVtb2dyYXBoaWNzX3NvYyRhdV9pZA0KICAgIG53YXZlcyA8LSBsZW5ndGgod2F2ZXMpDQogICAgbmV0cyA8LSBhcnJheSgwLCBkaW0gPSBjKG53YXZlcywgbGVuZ3RoKGlkcyksIGxlbmd0aChpZHMpKSwgZGltbmFtZXMgPSBsaXN0KHdhdmUgPSAxOm53YXZlcywgaWRzLA0KICAgICAgICBpZHMpKQ0KICAgIGRpbW5hbWVzKG5ldHMpDQoNCiAgICAjIHN0ZXAgMw0KICAgIGRmX3dvcmtzIDwtIHRpYmJsZSh3b3Jrc19pZCA9IHVubGlzdChsYXBwbHkoc2Nob2xhcnNfc2VsJHdvcmssIGZ1bmN0aW9uKGwpIGwkaWQpKSwgd29ya3NfYXV0aG9yID0gdW5saXN0KGxhcHBseShzY2hvbGFyc19zZWwkd29yaywNCiAgICAgICAgZnVuY3Rpb24obCkgbCRhdXRob3IpLCByZWN1cnNpdmUgPSBGQUxTRSksIHdvcmtzX3llYXIgPSB1bmxpc3QobGFwcGx5KHNjaG9sYXJzX3NlbCR3b3JrLCBmdW5jdGlvbihsKSBsJHB1YmxpY2F0aW9uX3llYXIpLA0KICAgICAgICByZWN1cnNpdmUgPSBGQUxTRSkpDQoNCiAgICBkZl93b3JrcyA8LSBkZl93b3Jrc1shZHVwbGljYXRlZChkZl93b3JrcyksIF0NCg0KICAgICMgc3RlcCA0DQogICAgaWYgKHR5cGUgPT0gImZpcnN0Iikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ28gPC0gZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZFsxXQ0KICAgICAgICAgICAgICAgIGFsdGVycyA8LSBkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkWy0xXQ0KICAgICAgICAgICAgICAgIGlmIChzdW0oaWRzICVpbiUgZWdvKSA+IDAgJiBzdW0oaWRzICVpbiUgYWx0ZXJzKSA+IDApIHsNCiAgICAgICAgICAgICAgICAgIG5ldHNbaiwgd2hpY2goaWRzICVpbiUgZWdvKSwgd2hpY2goaWRzICVpbiUgYWx0ZXJzKV0gPC0gMQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIGlmICh0eXBlID09ICJsYXN0Iikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ28gPC0gcmV2KGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWQpWzFdDQogICAgICAgICAgICAgICAgYWx0ZXJzIDwtIHJldihkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkKVstMV0NCiAgICAgICAgICAgICAgICBpZiAoc3VtKGlkcyAlaW4lIGVnbykgPiAwICYgc3VtKGlkcyAlaW4lIGFsdGVycykgPiAwKSB7DQogICAgICAgICAgICAgICAgICBuZXRzW2osIHdoaWNoKGlkcyAlaW4lIGVnbyksIHdoaWNoKGlkcyAlaW4lIGFsdGVycyldIDwtIDENCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQoNCiAgICBpZiAodHlwZSA9PSAiYWxsIikgew0KICAgICAgICBmb3IgKGogaW4gMTpud2F2ZXMpIHsNCiAgICAgICAgICAgIGRmX3dvcmtzX3cgPC0gZGZfd29ya3NbZGZfd29ya3Mkd29ya3NfeWVhciA+PSB3YXZlc1tbal1dWzFdICYgZGZfd29ya3Mkd29ya3NfeWVhciA8PSB3YXZlc1tbal1dWzJdLA0KICAgICAgICAgICAgICAgIF0NCiAgICAgICAgICAgIGZvciAoaSBpbiAxOm5yb3coZGZfd29ya3NfdykpIHsNCiAgICAgICAgICAgICAgICBlZ29zIDwtIGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWQNCiAgICAgICAgICAgICAgICBpZiAoc3VtKGlkcyAlaW4lIGVnb3MpID4gMCkgew0KICAgICAgICAgICAgICAgICAgbmV0c1tqLCB3aGljaChpZHMgJWluJSBlZ29zKSwgd2hpY2goaWRzICVpbiUgZWdvcyldIDwtIDENCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICB9DQogICAgb3V0cHV0IDwtIGxpc3QoKQ0KICAgIG91dHB1dCRkYXRhIDwtIHNjaG9sYXJzX3NlbA0KICAgIG91dHB1dCRuZXRzIDwtIG5ldHMNCiAgICByZXR1cm4ob3V0cHV0KQ0KfQ0KYGBgDQoNCg0KRXhhbXBsZSBpbiBjbGFzcyBmcm9tIDEwIE9jdG9iZXINClNpZW5hIGRlcGVuZGVudCB2YXJpYWJsZSANCg0KYGBge3J9DQojIFN0ZXAgMTogbG9hZCBkYXRhDQpsaWJyYXJ5KFJTaWVuYSkNCj9zaWVuYURlcGVuZGVudCAjbG9vayBmb3IgZXhhbXBsZXMgLSBzY3JpcHQgZm9yIGhvdyB0byBydW4gc3R1ZmYgDQoNCg0KIyB0aGVuIGNoZWNrIHdhdmVzIGF2YWlsYWJsZQ0KczUwMSAjbmV0d29yayBhdCB0aW1lcG9pbnQgMQ0KczUwMiAjbmV0d29yayBhdCB0aW1lcG9pbnQgMg0KczUwMyAjbmV0d29yayBhdCB0aW1lcG9pbnQgDQoNCg0KbXluZXQxIDwtIHNpZW5hRGVwZW5kZW50KGFycmF5KGMoczUwMSwgczUwMiwgczUwMyksIGRpbT1jKDUwLCA1MCwgMykpKQ0KbXliZWggPC0gc2llbmFEZXBlbmRlbnQoczUwYSwgdHlwZT0iYmVoYXZpb3IiKQ0KDQogIyBsb29rIGZvciBzbW9raW5nIGFuZCBkcmlua2luZyBiZWhhdmlvcnMNCg0Kc21va2UgPC0gczUwcyAjdGltZSB2YXJ5aW5nIGNvdmFyaWF0ZS4gVGltZSBjb25zdGFudCBjb3ZhciAtIHZhckNvdmFyDQpzbW9rZSA8LSB2YXJDb3ZhcihzNTBzKQ0KDQpteWRhdGFfZXhhbXBsZSA8LSBzaWVuYURhdGFDcmVhdGUobXluZXQxLCBteWJlaCwgc21va2UpDQoNCg0KDQojIFN0ZXAgMjogbG9vayBhdCBkYXRhDQojcHJpbnQgcmVwb3J0IG9uIGRhdGEgcmVwb3J0cw0KDQpwcmludDAxUmVwb3J0KG15ZGF0YV9leGFtcGxlKQ0KDQoNCiMgU3RlcCAzOiBhZGQgZWZmZWN0cyANCm15ZWZmX2V4YW1wbGUgPC0gZ2V0RWZmZWN0cyhteWRhdGFfZXhhbXBsZSkNCm15ZWZmX2V4YW1wbGUNCg0KDQoNCm15ZWZmX2V4YW1wbGUgPC0gaW5jbHVkZUVmZmVjdHMobXllZmZfZXhhbXBsZSwgdW5lcXVhbFgsIG5hbWU9Im15bmV0MSIsIGludGVyYWN0aW9uMSA9ICJzbW9rZSIpDQpteWVmZl9leGFtcGxlDQoNCg0KI21ha2UgYWxnb3JpdGhtIHRvIHRoZW4gZXN0aW1hdGUgaXQNCmFsZ29fZXggPC0gc2llbmFBbGdvcml0aG1DcmVhdGUocHJvam5hbWUgPSAidGVzdF9leCIpDQphbnN3ZXJfZXggPC0gc2llbmEwNyhhbGdvX2V4LCBkYXRhPW15ZGF0YV9leGFtcGxlLCBlZmZlY3RzPW15ZWZmX2V4YW1wbGUsIHJldHVybkRlcHMgPSBUUlVFKQ0KDQphbnN3ZXJfZXgNCg0KDQojZG9lcyBpdCBjaGFuZ2UgaWYgZGVwZW5kZW50IFggDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAibXliZWgiKSAjbmFtZSA9IG5ldHdvcmsgZGVwZW5kZW50IHZhcmlhYmxlLCBpbnRlcmFjdGlvbiAxIGlzIGNvdmFyaWF0ZSAoc21va2luZykgLSBpZiBoYXZlIG11bHRpcGxlIG5ldG93cmtzLCB0aGVuIGNvdWxkIGhhdmUgdW5lcXVhbFggd2l0aCByZXNwZWN0IHRvIFguIFdlIHJlcGxhY2VkIHNtb2tlIHdpdGggbXkgYmVoYXZpb3IsIGFuZCByZXJ1biB0aGUgc2llbmEgbW9kZWwuIFRoaXMgaXMgYW4gYWxnb3JpdGhtLCBjYW4gYXNrIFJTaWVuYSB0byByZWZlcmVuY2UgcHJldmlvdXMgcmVzdWx0IHdpdGggJ3ByZXZhbnM9QU5TJyBhZnRlciByZXR1cm5EZXB0cyA9IFRSVUUNCmFuc3dlcl9leCA8LSBzaWVuYTA3KGFsZ29fZXgsIGRhdGE9bXlkYXRhX2V4YW1wbGUsIGVmZmVjdHM9bXllZmZfZXhhbXBsZSwgcmV0dXJuRGVwcyA9IFRSVUUpDQoNCmFuc3dlcl9leA0KIyBsb29raW5nIGF0IHJlc3VsdHMsIG15YmVoID0gZHJpbmtpbmcgLS0gZWdvIGxlc3MgbGlrZWx5IHRvIHNwZW5kIHRpbWUgd2l0aCBwZW9wbGUgd2hvIGRyaW5rIG1vcmUgb3IgbGVzcyB0aGFuIHRoZW0uIGVnbyBhbHNvIGxlc3MgbGlrZWx5IHRvIHNwZW5kIHRpbWUgd2l0aCBwZW9wbGUgd2hvIHNtb2tlIG1vcmUgb3IgbGVzcywgdG8gYSBsZXNzZXIgZXh0ZW50LiBDYW4gdXNlIHVuZXF1YWxYIGZvciBkZXBlbmRlbnQgdmFyaWFibGVzIGFuZCBjb3ZhcmlhdGVzLiBrZXkgZGlmZmVyZW5jZSBpbiBlc3RpbWF0aW9uIHByb2NlZHVyZTogDQojIHdlIGFyZSBhbHNvIG1vZGVsaW5nIGJlaGF2aW9yYWwgcmVzdWx0cyAtIGJlaGF2aW9yIGNoYW5naW5nIG92ZXIgdGltZSwgc2ltdWxhdGVkIHZpYSBtaW5pc3RlcCBsb2dpYyAob25lIHN0ZXAgdXAgb3IgZG93bikuIFRoZSBjcnVjaWFsIGRpZmZlcmVuY2U6IGR1cmluZyB0aGUgYWxnb3JpdGhtIA0KI0lmIGNvdW50IHN0YXRpc3RpYyBmb3Igc21va2UsIHRoZW4gYmV0d2VlbiB0aW1lIHBvaW50IDEgYW5kIDIgd2UgdXNlIHZhbHVlIGZyb20gdGltZXBvaW50IDEuIGJldHdlZW4gMi0zLCB1c2UgdGltZSBwb2ludCAyLiBCdXQgd2l0aGluIHRoZSB2YXJpYWJsZSwgdGhlIGVnbyBsZXZlbCBiZWhhdmlvciBpcyBjaGFuZ2luZy4gaXMgbm90IHVzaW5nIHRoZSB2YWx1ZSBhcyBvYnNlcnZlZCBhdCB0MSAtIGl0IGlzIHVzaW5nIHRoZSB2YWx1ZSBhcyBpcyBjdXJyZW50bHkgc2ltdWxhdGVkLiANCg0KDQoNCg0KDQojY291bGQgZXhjbHVkZSB2YXJpYWJsZSB0byB0aGVuIGluY2x1ZGUgYXMgY292YXJpYXRlIGVmZmVjdC4gDQoNCm15YmVoIDwtIHNpZW5hRGVwZW5kZW50KHM1MGEsIHR5cGU9ImJlaGF2aW9yIikgI2RlZmluZWQgYXMgZGVwZW5kZW50IHZhcmlhYmxlIA0KZHJpbmtpbmcgPC0gdmFyQ292YXIoczUwYSkgI2RlZmluZWQgYXMgY292YXJpYXRlIHZhcmlhYmxlIA0KDQojdXBkYXRlIGRhdGEgb2JqZWN0OiANCm15ZGF0YV9leGFtcGxlIDwtIHNpZW5hRGF0YUNyZWF0ZShteW5ldDEsIG15YmVoLCBkcmlua2luZywgc21va2UpDQoNCg0KI2FuZCBlZmZlY3RzIG9iamVjdDogDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAic21va2UiKQ0KDQpteWVmZl9leGFtcGxlIDwtIGluY2x1ZGVFZmZlY3RzKG15ZWZmX2V4YW1wbGUsIHVuZXF1YWxYLCBuYW1lPSJteW5ldDEiLCBpbnRlcmFjdGlvbjEgPSAiZHJpbmtpbmciKQ0KDQphbGdvX2V4MiA8LSBzaWVuYUFsZ29yaXRobUNyZWF0ZShwcm9qbmFtZSA9ICJ0ZXN0X2V4IikNCg0KYW5zd2VyX2V4IDwtIHNpZW5hMDcoYWxnb19leDIsIGRhdGE9bXlkYXRhX2V4YW1wbGUsIGVmZmVjdHM9bXllZmZfZXhhbXBsZSwgcmV0dXJuRGVwcyA9IFRSVUUpDQphbnN3ZXJfZXgNCg0KI3RoZW4gdGhlIG5ldHdvcmsgZHluYW1pY3MgY2hhbmdlIA0KIyBpbnRlcnByZXRhdGlvbiBvZiB0aGUgcmF0ZSBjb25zdGFudCAtIHRoZSBhdmVyYWdlIGFtb3VudCBvZiBtaW5pc3RlcHMgZWFjaCBlZ28gaXMgbWFraW5nIGJldHdlZW4gdGhlIHR3byBvYnNlcnZhdGlvbnMNCg0KI2JlaGF2aW9yYWwgZHluYW1pY3M6IA0KIyB0aGUgcmF0ZSBjb25zdGFudDogdGhlIG51bWJlciBvZiBzdGVwcyBpbiB0aGUgYmVoYXZpb3JhbCBhc3BlY3QgDQoNCiNzdGF0aXN0aWMgZm9yIGxpbmVhciBzaGFwZSAtIGxpbmVhciBzaGFwZSBlZmZlY3QgLSB0aGUgdmFsdWUgb2YgdGhlICpjZW50ZXJlZCogYmVoYXZpb3JhbCB2YXJpYWJsZSAoYXZlcmFnZSBpbiB0aGUgdG90YWwgc2FtcGxlKS4gDQojIGlmIHBvc2l0aXZlLCB0cnkgdG8gaW5jcmVhc2UgYmVoYXZpb3IuIGVmZmVjdCBpcyB6MSAoemVkIHNjb3JlKSwgd2l0aCB0aGUgb3B0aW9ucyBvZiAxLCAwLCBvciAtMS4gYmVoYXZpb3IgaW5jcmVhc2VzIGJlY2F1c2UgcG9zaXRpdmVseSBldmFsdWF0ZXMgMSBtb3JlIHRoYW4gMCwgbW9yZSB0aGFuIC0xLiBBdCBzb21lIHBvaW50LCB0aG91Z2gsIGJlaGF2aW9yIHdpbGwgc3RvcCBpbmNyZWFzaW5nIC0gdGhhdCBpcyB6MiAoc3F1YXJlZCEpLiBzbywgcGFyYW1ldGVyIG1vZGVyYXRlcyBpdHNlbGYgd2l0aCB0aW1lPz8gDQoNCiMgdGhlc2UgYXJlIHRoZSBtaW5pbXVtIGVmZmVjdHMgdG8gaW5jbHVkZSwgYmVjYXVzZSBpdCBwcmVkaWN0cyBtZWFuIHZhbHVlIG9ic2VydmUgaW4gZGF0YXNldC4gMiBwYXJhbWV0ZXJzIC0gZXN0aW1hdGUgbWVhbiBiZWhhdmlvci4gYmFzZWQgb24gbW9kZWwgcmVzdWx0cywgd2hhdCBpcyB0aGUgbWVhbiB2YWx1ZS4gDQoNCiMgYmVoYXZpb3JhbCB2YXJpYWJsZXMgaW4gZGF0YXNldCAtIGV2ZXJ5dGhpbmcgb2JzZXJ2ZWQgdGhhdCBjaGFuZ2VzLiBleC4sIHBvc2l0aW9uIChmdW5jdGllKSwgY2l0YXRpb25zLCBpbnRlcmRpc2NpcGxpbmFyaXR5IHNjb3JlLiBQcm9ibGVtOiBpcyB0aW1lIHdpbmRvdyBsYXJnZSBlbm91Z2h0IHRvIHNlZSBjaGFuZ2U/IGFuZCBvdmVyIHRpbWUsIGJlaGF2aW9yYWwgdmFyaWFibGUgaXMgb25seSBjaGFuZ2luZyAtIHdoaWNoIHRoZW4gbXVzdCBiZSBjYWxjdWxhdGVkIGFzIGNvbnRpbnVvdXMgZGVwZW5kZWQgdmFyaWFibGUuIA0KDQoNCmBgYA0KDQoNCg==